#include <time.h>
#include <string.h>

 
#include "base.h"

#ifdef __linux__
#include <sys/types.h>
#include <regex.h>
#endif

#ifdef WIN32
#include "3rdpart/regex/regex.h"
#endif

BOOL getStrTimeNow(char *strNow,time_t *p_tt) {
    time_t tNow;
    struct tm *tmNow;
    char *wday[]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

    ASSERT(NULL!=strNow);

    if (strNow==NULL)
        return FALSE;

    time(&tNow);
    if (p_tt!=NULL)
        *p_tt=tNow;

    tmNow=localtime(&tNow);
    sprintf(strNow,"%d-%02d-%02d-%s-%02d:%02d:%02d",(1900+tmNow->tm_year),(1+tmNow->tm_mon),tmNow->tm_mday,wday[tmNow->tm_wday],tmNow->tm_hour,tmNow->tm_min,tmNow->tm_sec);

    return TRUE;
}

/*! tset
 *
 */
time_t getUTCNow() {
    return time((time_t *)NULL);
}

int milisleep(uint64 mili_sec){
    struct timespec ts;
    ts.tv_sec = mili_sec / 1000;
    ts.tv_nsec = (mili_sec % 1000) * 1000000;
    return nanosleep(&ts, NULL);
}

static inline uint64 rdtsc(){
        unsigned int lo, hi;
#ifdef __linux__
        /* We cannot use "=A", since this would use %rax on x86_64 */
        __asm__ __volatile__ (
                "rdtsc" 
                : "=a" (lo), "=d" (hi)
                );
#else
#error "not done yet "
#endif
        return (uint64)hi << 32 | lo;
}


static uint64 _cal_cpu_hz()
{
    uint64 t1;
    uint64 t2;

    t1 = rdtsc();
    milisleep(100);
    t2 = rdtsc();
    return (t2-t1)*10;
}

inline uint64 get_cpu_hz(){
    char buf[1024], *p[2];
    static uint64 freq = 0;

    if (0 != freq) {
        return freq;
    }

    FILE* fp = fopen("/proc/cpuinfo", "rb");
    if (fp != NULL) {
        while (fgets(buf, sizeof(buf), fp) != NULL) {
            if (2==splitstring(buf, ':', p, 2) && 0==strnicmp(p[0], "cpu MHz", 7)) {
                double f = strtod(p[1], NULL);
                freq = (uint64)(f * 1000000.0);
                //printf("freq=%u\n", freq);
                break;
            }
        }
        fclose(fp);
    }

    if (0 == freq) {
        freq = _cal_cpu_hz();
    }
    return freq;
}

BOOL start_timer(struct base_timer *pt){
    ASSERT(pt!=NULL);
    pt->start = rdtsc();
    pt->is_run = TRUE;
    return TRUE;
}

BOOL stop_timer(struct base_timer *pt){
    pt->end = rdtsc();
    pt->is_run = FALSE;
    return TRUE;
}

BOOL is_timer_run(const struct base_timer *pt){
    return pt->is_run == TRUE ? TRUE : FALSE;
}

double get_passed_ms(const struct base_timer *pt){
    ASSERT(pt!=NULL);
    ASSERT(pt->start>=0);
    return ( (double)(rdtsc() - pt->start) / get_cpu_hz() ) * 1000;
}

double get_passed_sec(const struct base_timer *pt){
    ASSERT(pt!=NULL);
    ASSERT(pt->start>=0);
    ( (double)(rdtsc() - pt->start) / get_cpu_hz() );
}
